package GoogleServices;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.google.gdata.client.calendar.CalendarQuery;
import com.google.gdata.data.DateTime;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.calendar.CalendarEventEntry;
import com.google.gdata.data.calendar.CalendarEventFeed;
import com.google.gdata.data.calendar.EventWho;
import com.google.gdata.data.extensions.When;
import com.google.gdata.data.extensions.Where;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;

import dto.utils.SingleEvent;

/**
 * 
 * @author Rino
 *
 *  Classe che fornisce un' insieme di Api relative a Google Calendar che
 *  saranno utilizzate  dagli agenti
 *   
 */

//REstituzione degli appuntamenti

public class GoogleCalendarCalls extends GoogleServices
{
	public static final long ORA = 3600000;

	public GoogleCalendarCalls(String username, String password) throws AuthenticationException{
		// TODO Auto-generated constructor stub
		super(username,password);
	}


	public static String getToday()
	{
		String today = DateTime.now().toUiString(); // "2009-01-19T11:21:26.256Z"
		today = today.substring(0, 10);
		return today;
	}
	
	public CalendarEventEntry getEvent(String idEvent) {
		
		try {
			String [] splittedIdEntry = idEvent.split("/");
			idEvent = splittedIdEntry[splittedIdEntry.length -1];
			
			URL entryUrl = new URL(feedUrlCalendar+"/"+idEvent);
			
			CalendarEventEntry eventEntry = calendarService.getEntry(entryUrl, CalendarEventEntry.class);
			
			return eventEntry;
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
	
	public void updateEvent(CalendarEventEntry eventEntry) {
		
		try {
			String idEvent = eventEntry.getId();
			
			String [] splittedIdEntry = idEvent.split("/");
			
			idEvent = splittedIdEntry[splittedIdEntry.length -1];
			
			URL entryUrl = new URL(feedUrlCalendar+"/"+idEvent);
			
			calendarService.update(entryUrl, eventEntry,"*");
		
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void removeEvent(String entryId) {
		
		try {
			String [] splittedEntryId = entryId.split("/");
			entryId = splittedEntryId[splittedEntryId.length - 1];
			String newUrl = feedUrlCalendar.toString().replace("%40", "@");
			newUrl = newUrl+"/"+entryId;
			URL url = new URL(newUrl);
			
			calendarService.delete(url,"*");
			
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * DANILO
	 * @param start
	 * @param end
	 * @return returns a list of SingleEvent in order by time representing all the events on the caller's calendar.
	 */
	public List<SingleEvent> getEventsByRange(final long start, final long end)
	{

		List<SingleEvent> eventi=new ArrayList<SingleEvent>();

		CalendarEventFeed myResultsFeed=null;
		try {
			myResultsFeed = calendarService.getFeed(feedUrlCalendar, CalendarEventFeed.class);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ServiceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 

		// create a new query object and set the parameters
		final CalendarQuery myQuery = new CalendarQuery(feedUrlCalendar);

		myQuery.setMinimumStartTime(new DateTime(start));
		myQuery.setMaximumStartTime(new DateTime(end));

		// send the request with the built query URL
		try
		{
			myResultsFeed = calendarService.query(myQuery, CalendarEventFeed.class);
		}
		catch (final IOException ex)
		{

		}
		catch (final ServiceException ex)
		{

		}

		for(CalendarEventEntry event : myResultsFeed.getEntries()) {

			@SuppressWarnings("rawtypes")
			Iterator i=event.getRepeatingExtensions().iterator();
			
			while(i.hasNext()){
				@SuppressWarnings("rawtypes")
				List list=(List) i.next();

				if(!list.isEmpty())
				{
					Object object = list.get(0);
					
					if(object instanceof When){

//						eventi.add(new SingleEvent( ((When)object).getStartTime().getValue(), ((When)object).getEndTime().getValue()));
						
						for(int j=1; j<list.size(); j++) {
							
							object = list.get(j);

							eventi.add(new SingleEvent(((When)object).getStartTime().getValue(),  ((When)object).getEndTime().getValue()));
						}
					}

				}

			}

			eventi.add(new SingleEvent(event.getTimes().get(0).getStartTime().getValue(), event.getTimes().get(0).getEndTime().getValue()));

		}

		//Collections.sort(eventi);


		return eventi;
	}

	// do a query by title to the calendar service and return number of event

	//isAvailable in time range
	public boolean isAvailableInTimeRange(final String start, final String end, final GoogleServices googleService)
			throws IOException, ServiceException
			{

		CalendarEventFeed myResultsFeed = calendarService.getFeed(feedUrlCalendar, CalendarEventFeed.class);

		// create a new query object and set the parameters
		final CalendarQuery myQuery = new CalendarQuery(feedUrlCalendar);
		myQuery.setMinimumStartTime(DateTime.parseDateTime(start));
		myQuery.setMaximumStartTime(DateTime.parseDateTime(end));

		// send the request with the built query URL
		try
		{
			myResultsFeed = calendarService.query(myQuery, CalendarEventFeed.class);
		}
		catch (final IOException ex)
		{
			Logger.getLogger(GoogleCalendarCalls.class.getName()).log(Level.SEVERE, null, ex);
		}
		catch (final ServiceException ex)
		{
			Logger.getLogger(GoogleCalendarCalls.class.getName()).log(Level.SEVERE, null, ex);
		}

		int entriesFound;

		entriesFound = myResultsFeed.getEntries().size();
		if (entriesFound == 0)
		{
			return true;
		}
		else
		{
			return false;
		}
			}


	/**
	 * 
	 * @param eventTitle
	 * @param eventDescription
	 * @param eventLocation
	 * @param event
	 * @return set an event 1 to 1 on the caller's calendar.
	 */

	public String setEvent(final String eventTitle, final String eventDescription, final String eventLocation,
			final SingleEvent event, final List<String> partecipants, TimeZone timeZone)
	{
		System.out.println("Inserisco l'evento sul calendario: \n Title: " + eventTitle + "\n Event Description: " + eventDescription
				+ "\n Event Location: " + eventLocation + "\n Event Start At: " + new Date(event.getStartTime()) + "\n Event End At:" 
				+ new Date(event.getEndTime()));

		URL postURL = null;
		try
		{
			postURL = new URL(feedUrlCalendar.toString());
		}
		catch (final MalformedURLException ex)
		{
			Logger.getLogger(GoogleCalendarCalls.class.getName()).log(Level.SEVERE, null, ex);
		}

		final CalendarEventEntry myEvent = new CalendarEventEntry();

		// set title and description
		myEvent.setTitle(new PlainTextConstruct(eventTitle));

		// create DateTime events and create a When object to hold them
		GregorianCalendar gregorianCalendarUTC = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
		gregorianCalendarUTC.setTimeInMillis(event.getStartTime());
		
		GregorianCalendar gregorianCalendarGMT = new GregorianCalendar(timeZone);
		gregorianCalendarGMT.setTimeInMillis(event.getStartTime());
		
		int differenza = gregorianCalendarGMT.get(Calendar.HOUR_OF_DAY) - gregorianCalendarUTC.get(Calendar.HOUR_OF_DAY);
		
		final DateTime startTime = new DateTime(event.getStartTime()+(ORA*differenza)); //, TimeZone.getDefault().getDSTSavings());
		
		final DateTime endTime = new DateTime(event.getEndTime()+(ORA*differenza)); //, TimeZone.getDefault().getDSTSavings());
		
		System.out.println("ST "+startTime+ "ED "+ endTime);
		
		final When eventTimes = new When();		
		eventTimes.setStartTime(startTime);
		eventTimes.setEndTime(endTime);
		myEvent.addTime(eventTimes);
		
		// add a Where object to add the location
		final Where eventPlace = new Where();
		eventPlace.setValueString(eventLocation);
		myEvent.addLocation(eventPlace);

		// ADDING Participants
		for(String partecipant : partecipants)
		{
			final EventWho who = new EventWho();
			who.setEmail(partecipant.replace("#", "@"));
			myEvent.addParticipant(who);
		}				
		
		myEvent.setSendEventNotifications(true);

		try
		{
			// POST the request and receive the response
			CalendarEventEntry newEventEntry = calendarService.insert(postURL, myEvent);
			
			System.out.println("java: ENTRY ADDED to Calendar!");
			
			return newEventEntry.getId();
		}
		catch (final IOException ex)
		{
			Logger.getLogger(GoogleCalendarCalls.class.getName()).log(Level.SEVERE, null, ex);
		}
		catch (final ServiceException ex)
		{
			Logger.getLogger(GoogleCalendarCalls.class.getName()).log(Level.SEVERE, null, ex);
		}
		
		return "";
	}


	//events in time range using CalendarEntry
		public List<CalendarEventEntry> getEventsByRangeCalendarEventEntry(long start, long end)
		{

			List<CalendarEventEntry> eventi=new ArrayList<CalendarEventEntry>();

			CalendarEventFeed myResultsFeed=null;
			try {
				myResultsFeed = calendarService.getFeed(feedUrlCalendar, CalendarEventFeed.class);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ServiceException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 

			// create a new query object and set the parameters
			final CalendarQuery myQuery = new CalendarQuery(feedUrlCalendar);

			myQuery.setMinimumStartTime(new DateTime(start));
			myQuery.setMaximumStartTime(new DateTime(end));

			// send the request with the built query URL
			try
			{
				myResultsFeed = calendarService.query(myQuery, CalendarEventFeed.class);
			}
			catch (final IOException ex)
			{

			}
			catch (final ServiceException ex)
			{

			}

			for(CalendarEventEntry event : myResultsFeed.getEntries()) {

				
				eventi.add(event);
			}

			return eventi;
		}
}
